package com.hyd.tweet.user;

import com.google.appengine.api.datastore.Key;
import com.hyd.tweet.twitter.TwitterUserUtils;
import com.hyd.tweet.util.ArrayUtils;
import com.hyd.tweet.util.Cache;
import com.hyd.tweet.util.DateUtils;
import com.hyd.tweet.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import twitter4j.Status;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import java.io.Serializable;
import java.util.Calendar;

/**
 * (description)
 *
 * @author yiding.he
 */
@PersistenceCapable(detachable = "true")
public class User implements Serializable {
    
    static final Logger log = LoggerFactory.getLogger(User.class);

    private static final int DEFAULT_UPDATE_INTERVAL = 10;  // 缺省刷新间隔时间 10 分钟

    public static final String DEFAULT_SLEEP_HOURS = "0 1 2 3 4 5 6 7";

    ///////////////////////////////////////////////////////

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    @Persistent
    private String account;

    @Persistent
    private String token;

    @Persistent
    private String tokenSecret;

    @Persistent
    private Long lastTimelineStatusId;

    @Persistent
    private String messageStatus;

    @Persistent
    private Integer updateInterval = DEFAULT_UPDATE_INTERVAL;  // 刷新间隔，单位：分钟

    @Persistent
    private String sleepingHours = DEFAULT_SLEEP_HOURS;
    
    @Persistent
    private Long lastAtmeStatusId;

    @Persistent
    private Long lastDirectMessageId;

    public Long getLastAtmeStatusId() {
        return lastAtmeStatusId;
    }

    public void setLastAtmeStatusId(Long lastAtmeStatusId) {
        this.lastAtmeStatusId = lastAtmeStatusId;
    }

    public Long getLastDirectMessageId() {
        return lastDirectMessageId;
    }

    public void setLastDirectMessageId(Long lastDirectMessageId) {
        this.lastDirectMessageId = lastDirectMessageId;
    }

    public void setSleepingHours(String sleepingHours) {
        this.sleepingHours = sleepingHours;
    }

    public int getUpdateInterval() {
        if (updateInterval == null || updateInterval == 0) {
            updateInterval = DEFAULT_UPDATE_INTERVAL;
        }
        return updateInterval;
    }

    public void setUpdateInterval(Integer updateInterval) {
        if (updateInterval == null) {
            updateInterval = DEFAULT_UPDATE_INTERVAL;
        }
        this.updateInterval = updateInterval;
    }

    public String getMessageStatus() {
        return messageStatus;
    }

    public void setMessageStatus(String messageStatus) {
        this.messageStatus = messageStatus;
    }

    public Long getLastTimelineStatusId() {
        return lastTimelineStatusId;
    }

    public void setLastTimelineStatusId(Long lastTimelineStatusId) {
        this.lastTimelineStatusId = lastTimelineStatusId;
    }

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getTokenSecret() {
        return tokenSecret;
    }

    public void setTokenSecret(String tokenSecret) {
        this.tokenSecret = tokenSecret;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("User");
        sb.append("{account='").append(account).append('\'');
        sb.append(", lastTimelineStatusId=").append(lastTimelineStatusId);
        sb.append(", messageStatus='").append(messageStatus).append('\'');
        sb.append(", sleepingHours=").append(sleepingHours);
        sb.append(", updateInterval=").append(updateInterval);
        sb.append(", rollerPosition=").append(rollerPosition);
        sb.append(", fromLastUpdate=").append(System.currentTimeMillis() - lastUpdate);
        sb.append('}');
        return sb.toString();
    }

    public void saveToCache() {
        Cache.put(account, this);
    }

    public boolean isReceivingMessage() {
        return (StringUtils.isEmpty(getMessageStatus()) ||
                getMessageStatus().equals("ready") ||
                getMessageStatus().equals("auto")) &&
                !isSleeping();
    }

    public boolean isSleeping() {
        if (sleepingHours == null || StringUtils.isEmpty(sleepingHours)) {
            return false;
        }

        int utcOffset = TwitterUserUtils.getCurrentTwitterUser(getAccount()).getUtcOffset();

        Calendar c = DateUtils.getGMTTime();
        c.add(Calendar.SECOND, utcOffset);
        int h = c.get(Calendar.HOUR_OF_DAY);

        return ArrayUtils.contains(sleepingHours.split("[ ]+"), String.valueOf(h));
    }
    
    /////////////////////////////////////////

    @NotPersistent
    private long lastUpdate = 0;

    public long getLastUpdate() {
        return lastUpdate;
    }

    public void setLastUpdate(long lastUpdate) {
        this.lastUpdate = lastUpdate;
    }

    /////////////////////////////////////////

    @NotPersistent
    private int rollerPosition = 0;

    private static final int MAX_ROLLER_ID = 99;

    public int pushToRoller(Status status) {
        rollerPosition = (rollerPosition + 1) % (MAX_ROLLER_ID + 1);
        Cache.put("status_" + account + "_" + rollerPosition, status);
        return rollerPosition;
    }

    public Status getStatusByRollerId(int rollerId) {
        return Cache.get("status_" + account + "_" + rollerId);
    }

    public String getUnavailableTip() {
        if (isReceivingMessage()) {
            return "";
        }

        if (isSleeping()) {
            return "(您当前处于休息状态。要自动接收消息，请用 /sleep 命令修改您的休息时间，或者在推特上修改您所在时区)";
        } else {
            return "(您当前不在接收消息状态。要自动接收消息，请发送 /start 命令)";
        }
    }
}
